//Copyright 2011 - Jonathan Allen

using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;

namespace Granite.Metadata
{
	/// <summary>
	/// Cache's metadata feteched via reflection.
	/// </summary>
	public static class MetadataCache
	{
		readonly static Dictionary<Type, ClassMetadata> s_ModelInfo = new Dictionary<Type, ClassMetadata>();

		readonly static object s_syncRoot = new object();

		/// <summary>
		/// Gets the metadata for the indicated type.
		/// </summary>
		/// <param name="type">The type of interest</param>
		/// <returns>A thread-safe copy of the class's metadata</returns>
		/// <remarks>Actually fetching the metadata requires taking a lock. Therefore it is advisable to locally cache the metadata as well.</remarks>
		[Pure]
		public static ClassMetadata GetMetadata(Type type)
		{
			Contract.Ensures(Contract.Result<ClassMetadata>() != null);

			if (type == null)
				throw new ArgumentNullException("type", "type is null.");

			lock (s_syncRoot)
			{
				ClassMetadata result;
				if (!s_ModelInfo.TryGetValue(type, out result))
				{
					result = new ClassMetadata(type);
					s_ModelInfo.Add(type, result);
				}
				Contract.Assume(result != null);
				return result;
			}
		}

	}
}
